package generator

import (
	"kumachan/interpreter/compiler/checker/checked"
	rt "kumachan/interpreter/runtime/def"
)

type Statistics struct {
	*GlobalStatistics
	Config  StatisticsConfiguration
}
type StatisticsConfiguration struct {
	FuncKey  rt.Symbol
}
func (stat *Statistics) MarkUnused(binding *checked.LocalBinding) {
	if stat.GlobalStatistics == nil {
		return
	}
	stat.GlobalStatistics.UnusedBindings[binding] = struct{}{}
}
func (stat *Statistics) MarkDepTo(f rt.Symbol) {
	if stat.GlobalStatistics == nil {
		return
	}
	var graph = stat.GlobalStatistics.DependencyGraph
	var this = stat.Config.FuncKey
	if graph[this] == nil {
		graph[this] = make(map[rt.Symbol] struct{})
	}
	var this_deps = graph[this]
	// direct edge
	this_deps[f] = struct{}{}
	// forward propagation
	for f_dep := range graph[f] {
		this_deps[f_dep] = struct{}{}
	}
	// backward propagation
	// TODO: optimization may be necessary
	var q = [] rt.Symbol { this }
	var visited = make(map[rt.Symbol] struct{})
	for len(q) > 0 {
		var x = q[0]
		q = q[1:]
		visited[x] = struct{}{}
		for y, y_deps := range graph {
			var _, x_deps_this = y_deps[x]
			if x_deps_this {
				for this_dep := range this_deps {
					y_deps[this_dep] = struct{}{}
				}
				var _, y_visited = visited[y]
				if !(y_visited) {
					q = append(q, y)
				}
			}
		}
	}
}

type GlobalStatistics struct {
	UnusedBindings    map[*checked.LocalBinding] struct{}
	DependencyGraph   map[rt.Symbol] map[rt.Symbol] struct{}
}
func NewGlobalStatistics() *GlobalStatistics {
	return &GlobalStatistics {
		UnusedBindings:  make(map[*checked.LocalBinding] struct{}),
		DependencyGraph: make(map[rt.Symbol] map[rt.Symbol] struct{}),
	}
}


